/**
* All Rights Reserved , Copyright (C) 2020 , 青岛鼎信通讯股份有限公司
*
* MpmProjectTeamService
* 项目任命-项目组成员
*
* 修改纪录
* 2020-12-28 版本：1.0 lanjianwei 创建。
* @version 版本：1.0
* @author 作者：lanjianwei
* 创建日期：2020-12-28
*/
package com.topscomm.mpm.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.topscomm.basic.exception.MessageException;
import com.topscomm.cbo.service.ICboMessageAppService;
import com.topscomm.cbo.service.ICboMessageSysService;
import com.topscomm.main.hessian.IBaseChangeLogService;
import com.topscomm.mpm.MpmSystemConst;
import com.topscomm.mpm.pojo.*;
import com.topscomm.mpm.utils.MessageUtil;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.SpringUtil;
import com.topscomm.pub.util.StringUtil;
import com.topscomm.tap.ITapService;
import com.topscomm.tap.TapEntity;
import com.topscomm.tap.common.DatacodeCache;
import org.apache.commons.beanutils.ConvertingWrapDynaBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.basic.util.PrimaryKeyUtil;
import com.topscomm.mpm.service.IMpmProjectTeamService;
import com.topscomm.mpm.service.impl.auto.MpmProjectTeamServiceAuto;
import com.topscomm.pub.util.StringBufferProxy;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

@Service(value = "mpmProjectTeamService")
@Scope(value = "singleton")
public class MpmProjectTeamService extends MpmProjectTeamServiceAuto implements IMpmProjectTeamService {

	@Autowired
	private ICboMessageAppService cboMessageAppService;
	@Autowired
	private ICboMessageSysService cboMessageSysService;
	@Autowired
	private MpmProjectService mpmProjectService;
	@Autowired
	private MpmProjectSuperviseService mpmProjectSuperviseService;
	@Autowired
	private DatacodeCache datacodeCache;
	@Autowired
	private IBaseChangeLogService baseChangeLogService;
	@Autowired
	private MpmProjectTaskService mpmProjectTaskService;

	/**
	 * @Title: beforeInsert
	 * @description:
	 * @param entity
	 * @author: lanjianwei
	 * @date: 2021年1月11日下午4:16:37
	 * @modify:
	 */
	@Override
	protected void beforeInsert(BasicEntity entity) {
		super.beforeInsert(entity);
		MpmProjectTeamEntity mpmProjectTeamEntity = (MpmProjectTeamEntity) entity;
		String userCode = mpmProjectTeamEntity.getUsercode();
		String appointmentType=mpmProjectTeamEntity.getAppointmenttype();
		String teamid = ConvertUtil.convertToString(mpmProjectTeamEntity.getTeamid());
		String projectRole = mpmProjectTeamEntity.getProjectrole();
		String appointmentId = String.valueOf(mpmProjectTeamEntity.getAppointmentid());
		StringBufferProxy whereSql = new StringBufferProxy();
		whereSql.appendLineSingle("appointmentid = '{0}' and enabled = 1", appointmentId);
		List<MpmProjectTeamEntity> mpmProjectTeamEntities = this.queryByWhere(whereSql.toString());
		for (MpmProjectTeamEntity mpmProjectTeamEntity2 : mpmProjectTeamEntities) {
			//工号、任命类型、工作组不能同时重复
			if (userCode.equals(mpmProjectTeamEntity2.getUsercode())
					&& teamid.equals(ConvertUtil.convertToString(mpmProjectTeamEntity2.getTeamid()))
					&& appointmentType.equals(mpmProjectTeamEntity2.getAppointmenttype())) {
				throw new ServiceException("项目组成员重复，请确认后再添加！");
			}
			// 一个工作组中不允许有多个组长
			if (MpmSystemConst.WorkGroupRoleCode.groupLeader.equals(projectRole)
					&& teamid.equals(ConvertUtil.convertToString(mpmProjectTeamEntity2.getTeamid()))
					&& appointmentType.equals(mpmProjectTeamEntity2.getAppointmenttype())
					&& projectRole.equals(mpmProjectTeamEntity2.getProjectrole())) {
				boolean flag = true;
				for(MpmProjectTeamEntity mpmProjectTeamEntity3 : mpmProjectTeamEntities) {
					// 当同一个组中存在对于同一个人的任命和撤销，即免去原组长，此时不应抛出异常
					if(mpmProjectTeamEntity3.getWorkgroup().equals(mpmProjectTeamEntity2.getWorkgroup())
							&& mpmProjectTeamEntity3.getUsercode().equals(mpmProjectTeamEntity2.getUsercode())
							&& !mpmProjectTeamEntity3.getAppointmenttype().equals(mpmProjectTeamEntity2.getAppointmenttype())) {
						flag = false;
						break;
					}
				}
				if(flag) {
					throw new ServiceException("项目组中只能有一个组长！");
				}
			}
		}
	}

	@Override
	@Transactional
	public List<MpmProjectTeamEntity> queryByAppointmentId(String appointmentId) {
		if (StringUtil.isEmpty(appointmentId)) {
			return new ArrayList<>();
		}
		StringBufferProxy sql = new StringBufferProxy();
		sql.appendSingle(MpmProjectTeamEntity.FieldAppointmentid + " =  {0} ", appointmentId);
		return this.queryByWhere(sql.toString());
	}

	public List<Map<String, Object>> queryTeamAndTeamType(String appointmentId) {
		if (StringUtil.isEmpty(appointmentId)) {
			return new ArrayList<>();
		}
		Map<String, Object> param = new HashMap<>();
		param.put("appointmentId", appointmentId);
		return this.queryMap(param, "selectTeamAndTeamType");

	}
	/**
	 * @author
	 * @date
	 * @description: 给项目组成员发送消息
	 * @modify:
	 */
	@Transactional
	public void sendMessageToPM(String sourceid, String sourcetype, String contentInfo, MpmProjectEntity mpmProjectEntity) throws Exception{
		// 如果项目经理为省总，则不发送审批完成消息
		if (mpmProjectService.queryIsProvinceManager(mpmProjectEntity.getProjectmanagercode())) {
			return;
		}
		// 消息内容和标题
		String title = "销售项目" + contentInfo + "变更通知";
		String dispProjectLevel = datacodeCache.getValueDynamic("MpmProjectLevel", mpmProjectEntity.getProjectlevel(), "code", "name");
		String content = "【" + dispProjectLevel + "级项目：" + mpmProjectEntity.getProjectname() + "】" + contentInfo + "变更审核已通过，请知悉";
		String userCode = mpmProjectEntity.getProjectmanagercode();
		String userName = mpmProjectEntity.getProjectmanager();
		// 系统消息
		Map<String, Object> sysMessageMap = mpmProjectSuperviseService.insertMessageSys(userCode, userName, title,
				content, mpmProjectEntity.getId(), sourcetype);
		cboMessageSysService.insertMap(sysMessageMap);
		// app消息
		Map<String, Object> appMessageMap = mpmProjectSuperviseService.insertMessageApp(userCode, title,
				content, mpmProjectEntity.getId(), sourcetype, 0);
		cboMessageAppService.insertMap(appMessageMap);
	}

	/**
	 * @author:zhangjunyao
	 * @date:2921-11-12
	 * @description: 给C、D级项目组成员发送App消息
	 * @modify:
	 */
	@Transactional
	public void sendAppMessageToCDProjectGroupMember(MpmProjectEntity entity, String sourceid, String sourcetype) throws Exception {
		// 查询项目和项目组成员
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("projectcode = '{0}' and {1} = '{2}' and enabled = '1'", entity.getProjectcode(),
                MpmProjectTeamEntity.FieldAppointmentid, sourceid);
		List<MpmProjectTeamEntity> mpmProjectTeamEntities = this.queryByWhere(sql.toString());
		if (CollectionUtils.isEmpty(mpmProjectTeamEntities)) {
			return;
		}
		// 将撤销任命人员剔除，得到项目组成员code，然后对项目组成员去重
		List<String> userCodeList = mpmProjectTeamEntities.stream().filter(item -> !MpmSystemConst.MPM_TAEM_APPOINTMENTTYPE_REVOKE.equals(item.getAppointmenttype()))
				.map(MpmProjectTeamEntity::getUsercode).distinct().collect(Collectors.toList());
		// 项目组成员剔除林总，林总不接收此消息
		userCodeList.remove("0070");
        Map<String, List<MpmProjectTeamEntity>> mpmProjectTeamEntityMap = mpmProjectTeamEntities.
                stream().collect(Collectors.groupingBy(MpmProjectTeamEntity::getUsercode));
		List<Map<String, Object>> appList = new ArrayList<Map<String, Object>>();
		List<Map<String, Object>> sysList = new ArrayList<Map<String, Object>>();
		// 消息内容和标题
		String title = "销售项目任命通知";
		String dispProjectLevel = datacodeCache.getValueDynamic("MpmProjectLevel", entity.getProjectlevel(), "code", "name");
		String content = "您被任命为【" + dispProjectLevel + "级项目：" + entity.getProjectname() +"】工作组成员，请登录系统查阅项目信息。";
		// 给项目组成员发送消息
		for (String userCode : userCodeList) {
		    String userName = mpmProjectTeamEntityMap.get(userCode).get(0).getUsername();
			// App消息
			Map<String, Object> appMessageMap = mpmProjectSuperviseService.insertMessageApp(userCode, title,
					content, entity.getId(), sourcetype, 0);
			appList.add(appMessageMap);
			// 系统消息
			Map<String, Object> sysMessageMap = mpmProjectSuperviseService.insertMessageSys(userCode, userName,
					title, content, entity.getId(), sourcetype);
			sysList.add(sysMessageMap);
		}
		cboMessageAppService.insertList(appList);
		cboMessageSysService.insertList(sysList);
	}
	/**
	 * @Title: updateBefore
	 * @description:
	 * @param map
	 * @author: houyuhang
	 * @date: 2022年02月10日
	 * @modify:
	 */
	@Override
	protected void updateBefore(Map<String, Object> map) {
		super.updateBefore(map);
		MpmProjectTeamEntity mpmProjectTeamEntity = new MpmProjectTeamEntity();
		mpmProjectTeamEntity.convertFromMap(map);
		String userCode = mpmProjectTeamEntity.getUsercode();
		String appointmentType=mpmProjectTeamEntity.getAppointmenttype();
		String teamid = ConvertUtil.convertToString(mpmProjectTeamEntity.getTeamid());
		String projectRole = mpmProjectTeamEntity.getProjectrole();
		String appointmentId = ConvertUtil.convertToString(mpmProjectTeamEntity.getAppointmentid());
		String id = ConvertUtil.convertToString(mpmProjectTeamEntity.getId());
		StringBufferProxy whereSql = new StringBufferProxy();
		whereSql.appendLineSingle("appointmentid = '{0}' and enabled = 1", appointmentId);
		List<MpmProjectTeamEntity> mpmProjectTeamEntities = this.queryByWhere(whereSql.toString());
		for (MpmProjectTeamEntity mpmProjectTeamEntity2 : mpmProjectTeamEntities) {
			//工号、任命类型、工作组不能同时重复
			if (userCode.equals(mpmProjectTeamEntity2.getUsercode())
					&& teamid.equals(ConvertUtil.convertToString(mpmProjectTeamEntity2.getTeamid()))
					&& appointmentType.equals(mpmProjectTeamEntity2.getAppointmenttype())
					&& !id.equals(ConvertUtil.convertToString(mpmProjectTeamEntity2.getId()))) {
				throw new ServiceException("项目组成员重复，请确认后再添加！");
			}
		}
	}
	/**
	 * @Title: queryProjectNum
	 * @description:
	 * @param tempList
	 * @author: houyuhang
	 * @date: 2022年04月18日
	 * @modify:
	 */
	public void queryProjectNum(List<Map<String, Object>> tempList) {
		if (CollectionUtil.isEmpty(tempList)) {
			return;
		}
		String usercode = tempList.stream().map(item -> "'" + ConvertUtil.convertToString(item.get("usercode")) + "'").collect(Collectors.joining(","));
		String projectState = "'" + MpmSystemConst.ProjectState.NormalFinish + "','" + MpmSystemConst.ProjectState.AbnormalFinish + "'";
		StringBufferProxy sql = new StringBufferProxy();
		// 项目未结项且任命审批完成且用户在任命组中
		sql.appendSingle(" {0}.{1} NOT IN ({2}) AND {3}.STATE = '9' AND {4}.{5} IN ({6}) ",
				MpmProjectEntity.tableName, MpmProjectEntity.FieldProjectstate, projectState,
				MpmProjectAppointmentEntity.tableName, MpmProjectTeamEntity.tableName, MpmProjectTeamEntity.FieldUsercode, usercode);
		Map<String, Object> paraMap = new HashMap<>();
		paraMap.put("whereSql", sql.toString());
		List<Map<String, Object>> mpmProjectList = this.queryMap(paraMap, "queryProjectNum");
		Map<String, List<Map<String, Object>>> mpmProjectMap = mpmProjectList.stream().collect(Collectors.groupingBy(item -> ConvertUtil.convertToString(item.get("usercode"))));
		for (Map<String, Object> temp : tempList) {
			String usercodeTemp = ConvertUtil.convertToString(temp.get("usercode"));
			List<Map<String, Object>> projectTemp = mpmProjectMap.get(usercodeTemp);
			temp.put("projectnum", CollectionUtil.isEmpty(projectTemp) ? 0 : projectTemp.size());
		}
	}
	/**
	 * @Title: insertRevoke
	 * @description:新增撤销项目组成员执行方法
	 * @author: houyuhang
	 * @date: 2022年05月16日
	 * @modify:
	 */
	@Transactional
	public void insertRevoke(Map<String, Object> paraMap) {
		List<MpmProjectTeamEntity> mpmProjectTeamEntities = this.queryByIds(ConvertUtil.convertToString(paraMap.get("ids")));
		if (CollectionUtil.isEmpty(mpmProjectTeamEntities)) {
			return;
		}
		// 撤销任命前，先检查有没有进行中的任务
		this.checkUnfinishTask(mpmProjectTeamEntities);
		// 撤销任命将对应人的任命类型由任命更改为撤销
		List<Map<String, Object>> updateList = new ArrayList<>();
		for (MpmProjectTeamEntity mpmProjectTeamEntity : mpmProjectTeamEntities) {
			Map<String, Object> updateMap = new HashMap<>();
			updateMap.put("id", mpmProjectTeamEntity.getId());
			updateMap.put("appointmenttype", MpmSystemConst.MPM_TAEM_APPOINTMENTTYPE_REVOKE);
			updateMap.put("revokedate", new Date());
			// 任命人员能否删除，0可以删除，1不能删除
			updateMap.put("candelete", 0);
			updateList.add(updateMap);
		}
		this.updateBatchMap(updateList);
	}

	/**
	 * @Title: insertRevoke
	 * @description:新增撤销项目组成员执行方法
	 * @author: houyuhang
	 * @date: 2022年05月16日
	 * @modify:
	 */
	@Transactional
	public void deleteRevoke(Map<String, Object> paraMap) {
		// 删除撤销任命时，将对应人的任命类型由撤销更改为任命
		List<MpmProjectTeamEntity> mpmProjectTeamEntities = this.queryByIds(ConvertUtil.convertToString(paraMap.get("ids")));
		if (CollectionUtil.isEmpty(mpmProjectTeamEntities)) {
			return;
		}
		List<Map<String, Object>> updateList = new ArrayList<>();
		for (MpmProjectTeamEntity mpmProjectTeamEntity : mpmProjectTeamEntities) {
			Map<String, Object> updateMap = new HashMap<>();
			updateMap.put("id", mpmProjectTeamEntity.getId());
			updateMap.put("appointmenttype", MpmSystemConst.MPM_TAEM_APPOINTMENTTYPE_APPOINT);
			updateMap.put("revokedate", null);
			// 任命人员能否删除，0可以删除，1不能删除
			updateMap.put("candelete", 1);
			updateList.add(updateMap);
		}
		this.updateBatchMap(updateList);
	}
	@Override
	public void setDispFields(Map<String, Object> mapRow, DatacodeCache datacodeCache) {
		super.setDispFields(mapRow, datacodeCache);
		String temp;
		if (mapRow.get("duty") != null) {
			temp = mapRow.get("duty").toString();
			String projectrole = ConvertUtil.convertToString(mapRow.get("projectrole"));
			String detailStr = ConvertUtil.convertToString(mapRow.get("moredetail"));
			int grouptype = ConvertUtil.convertToInt(mapRow.get("grouptype"));
			// 3种模板任命组
			if (grouptype > 0 && MpmSystemConst.WorkGroupRoleCode.groupWorker.equals(projectrole)) {
				mapRow.put("dispduty", concatDuty(grouptype,temp,detailStr));
			} else {
				mapRow.put("dispduty", temp);
			}
		}
	}
	/**
	 * @Title: concatDuty
	 * @description:将职责字段进行拼接
	 * @author: houyuhang
	 * @date: 2022年07月18日
	 * @modify:
	 */
	public String concatDuty(int grouptype, String duty, String detailStr) {
		if (StringUtil.isEmpty(duty)) {
			return "";
		}
		String[] dutyArr = duty.split(",");
		StringBuffer stringBuffer = new StringBuffer();
		int i=1;
		for(; i<=dutyArr.length ;i++) {
			if (grouptype == 3) {
				if (MpmSystemConst.GroupTypeOther.GroupTypeOtherThree.equals(dutyArr[i-1])) {
					stringBuffer.append(i + "、" + detailStr + "；");
				} else {
					stringBuffer.append(i + "、" + datacodeCache.getValueDynamic("MpmBusinessRoleDuty", dutyArr[i-1], "code", "name") + "；");
				}
			} else if (grouptype == 2) {
				if (MpmSystemConst.GroupTypeOther.GroupTypeOtherTwo.equals(dutyArr[i-1])) {
					stringBuffer.append(i + "、" + detailStr + "；");
				} else {
					stringBuffer.append(i + "、" + datacodeCache.getValueDynamic("MpmBidGuideDuty", dutyArr[i-1], "code", "name") + "；");
				}
			} else if (grouptype == 1) {
				if (MpmSystemConst.GroupTypeOther.GroupTypeOtherOne.equals(dutyArr[i-1])) {
					stringBuffer.append(i + "、" + detailStr + "；");
				} else {
					stringBuffer.append(i + "、" +datacodeCache.getValueDynamic("MpmBidBookDuty", dutyArr[i-1], "code", "name") + "；");
				}
			}
		}
		if (i == 2) {
			return stringBuffer.substring(2, stringBuffer.length() - 1);
		} else {
			return stringBuffer.toString();
		}
	}
	/***
	 * @description: 提醒项目PMO和省区PMO任命变更的内容
	 * @return
	 * @author: houyuhang
	 * @date: 2023/02/06
	 * @modify:
	 */
	public void sendMessageAppointmentToPMO(MpmProjectAppointmentEntity mpmProjectAppointmentEntity, MpmProjectEntity mpmProjectEntity) throws Exception {
		// 获取消息发送人（项目PMO和省区PMO）
		List<Map<String, Object>> receiverList = this.getMessageReceiverPMO(mpmProjectEntity.getDeptcommoncode());
		if (CollectionUtil.isEmpty(receiverList)) {
			return;
		}
		Map<String, Object> paraMap = new HashMap<>();
		paraMap.put("topSourceType", MpmProjectAppointmentEntity.tableName);
		paraMap.put("topSourceId", mpmProjectAppointmentEntity.getId());
		paraMap.put("sourceType", MpmProjectTeamEntity.tableName);
		List<Map<String, Object>> baseChangeLog = baseChangeLogService.queryChangeLogByOptions(paraMap);
		// 去除数据operatetype为del，值为上一次变更删除的项目组成员
		baseChangeLog = baseChangeLog.stream().filter(item -> MpmSystemConst.BaseLogOperateTypeEnum.Edit.equals(item.get("operatetype")) || MpmSystemConst.BaseLogOperateTypeEnum.Add.equals(item.get("operatetype"))).collect(Collectors.toList());
		// 如果项目组成员没有变化，不发送消息
		if (CollectionUtil.isEmpty(baseChangeLog)) {
			return;
		}
		// 将删除的数据operatetype修改为del，发送消息给变更人员
		for (Map<String, Object> logMap : baseChangeLog) {
			if (MpmSystemConst.BaseLogOperateTypeEnum.Edit.equals(logMap.get("operatetype"))) {
				this.setChangelogOperate(logMap);
			}
		}
		// 拼接发送给PMO信息
		List<Map<String, Object>> appList = new ArrayList<>(), sysList = new ArrayList<>();
		this.getAppointmentInfoDetail(baseChangeLog, appList, sysList, mpmProjectEntity, receiverList);
		// 拼接发送给变更人的消息
		String teamid = baseChangeLog.stream().filter(item -> MpmSystemConst.BaseLogOperateTypeEnum.Edit.equals(item.get("operatetype")) || MpmSystemConst.BaseLogOperateTypeEnum.Add.equals(item.get("operatetype"))).map(item -> ConvertUtil.convertToString(item.get("sourceid"))).collect(Collectors.joining("','", "'", "'"));
		List<MpmProjectTeamEntity> mpmProjectTeamEntities = StringUtil.isEmpty(teamid) ? new ArrayList<>() : this.queryByIds(teamid);
		this.sendAppointmentChangeMessageToUser(baseChangeLog, appList, sysList, mpmProjectEntity, mpmProjectTeamEntities);
		// 消息批量插入
		cboMessageAppService.insertList(appList);
		cboMessageSysService.insertList(sysList);
	}
	/***
	 * @description: 获取任命变更详情内容
	 * @return
	 * @author: houyuhang
	 * @date: 2023/02/07
	 * @modify:
	 */
	public void getAppointmentInfoDetail(List<Map<String, Object>> baseChangeLog, List<Map<String, Object>> appList, List<Map<String, Object>> sysList, MpmProjectEntity mpmProjectEntity, List<Map<String, Object>> receiverList) {
		List<Map<String, String>> pmoList = new ArrayList<>();
		String title = "销售项目任命变更通知";
		String projectLevel = datacodeCache.getValueDynamic("MpmProjectLevel", mpmProjectEntity.getProjectlevel(), "code", "name");
		for (Map<String, Object> logMap : baseChangeLog) {
			Map<String, String> pmoMap = new HashMap<>();
			// 获取项目组成员具体信息,项目具体信息
			MpmProjectTeamEntity mpmProjectTeamEntity = this.queryById(ConvertUtil.convertToString(logMap.get("sourceid")));
			if (ObjectUtil.isEmpty(mpmProjectTeamEntity)) {
				continue;
			}
			if (MpmSystemConst.BaseLogOperateTypeEnum.Add.equals(logMap.get("operatetype"))) {
				// 变更类型为add，该用户为新增任命
				pmoMap.put("username", mpmProjectTeamEntity.getUsername());
				pmoMap.put("operatetype", "add");
				pmoList.add(pmoMap);
			} else if (MpmSystemConst.BaseLogOperateTypeEnum.Edit.equals(logMap.get("operatetype"))) {
				// 变更类型为edit,变更了哪些内容
				pmoMap.put("username", mpmProjectTeamEntity.getUsername());
				pmoMap.put("operatetype", "edit");
				pmoList.add(pmoMap);
			} else if (MpmSystemConst.BaseLogOperateTypeEnum.Del.equals(logMap.get("operatetype"))) {
				// 变更类型为del,删除的项目组成员
				pmoMap.put("username", mpmProjectTeamEntity.getUsername());
				pmoMap.put("operatetype", "del");
				pmoList.add(pmoMap);
			}
		}
		// 将pmolist处理为变更内容具体描述
		this.changeStrForPMOList(pmoList, appList, sysList, mpmProjectEntity, receiverList, title, projectLevel);
	}
	/***
	 * @description: 获取发送给pmo的变更内容描述
	 * @return
	 * @author: houyuhang
	 * @date: 2023/02/09
	 * @modify:
	 */
	public void changeStrForPMOList(List<Map<String, String>> pmoList, List<Map<String, Object>> appList, List<Map<String, Object>> sysList, MpmProjectEntity mpmProjectEntity, List<Map<String, Object>> receiverList, String title, String projectLevel) {
		// 新增、编辑、删除内容拼接
		StringBuffer stringBuffer = new StringBuffer();
		String addStr = pmoList.stream().filter(item -> MpmSystemConst.BaseLogOperateTypeEnum.Add.equals(item.get("operatetype"))).map(item -> ConvertUtil.convertToString(item.get("username"))).distinct().collect(Collectors.joining("、"));
		if(!StringUtil.isEmpty(addStr)) {
			stringBuffer.append("新增人员：").append(addStr).append("，");
		}
		String delStr = pmoList.stream().filter(item -> MpmSystemConst.BaseLogOperateTypeEnum.Del.equals(item.get("operatetype"))).map(item -> ConvertUtil.convertToString(item.get("username"))).distinct().collect(Collectors.joining("、"));
		if(!StringUtil.isEmpty(delStr)) {
			stringBuffer.append("删除人员：").append(delStr).append("，");
		}
		String editStr = pmoList.stream().filter(item -> MpmSystemConst.BaseLogOperateTypeEnum.Edit.equals(item.get("operatetype"))).map(item -> ConvertUtil.convertToString(item.get("username"))).distinct().collect(Collectors.joining("、"));
		if(!StringUtil.isEmpty(editStr)) {
			stringBuffer.append("发生变更人员：").append(editStr).append("，");
		}
		StringBufferProxy content = new StringBufferProxy();
		content.appendSingle("【{0}级项目：{1}】任命变更已完成，{2}请知悉。", projectLevel, mpmProjectEntity.getProjectname(), stringBuffer.toString());
		// app推送
		for (Map<String, Object> receiver : receiverList) {
			appList.add(MessageUtil.createMessageAppMap(ConvertUtil.convertToString(receiver.get("usercode")), title, content.toString(), mpmProjectEntity.getId(),
					MpmProjectAppointmentEntity.tableName, 0));
			sysList.add(MessageUtil.createMessageSysMap(ConvertUtil.convertToString(receiver.get("usercode")), ConvertUtil.convertToString(receiver.get("username")), title, content.toString(),
					mpmProjectEntity.getId(), MpmProjectAppointmentEntity.tableName));
		}
	}
	/***
	 * @description: 给发生变更的用户发送变更消息
	 * @return
	 * @author: houyuhang
	 * @date: 2023/02/13
	 * @modify:
	 */
	public void sendAppointmentChangeMessageToUser(List<Map<String, Object>> baseChangeLog, List<Map<String, Object>> appList, List<Map<String, Object>> sysList, MpmProjectEntity mpmProjectEntity, List<MpmProjectTeamEntity> mpmProjectTeamEntities) {
		if (CollectionUtil.isEmpty(mpmProjectTeamEntities)) {
			return;
		}
		// 同一个用户多个新增变更、只收到一条信息
		List<String> userList = new ArrayList<>();
		userList.addAll(mpmProjectTeamEntities.stream().map(MpmProjectTeamEntity::getUsercode).collect(Collectors.toList()));
		Set<String> userSet = new HashSet<>(userList);
		Map<String, String> userRef = new HashMap<>();
		userRef.putAll(mpmProjectTeamEntities.stream().collect(Collectors.toMap(MpmProjectTeamEntity::getUsercode,MpmProjectTeamEntity::getUsername, (v1, v2) -> v1)));
		String title = "销售项目任命变更通知";
		String projectLevel = datacodeCache.getValueDynamic("MpmProjectLevel", mpmProjectEntity.getProjectlevel(), "code", "name");
		// 根据用户code对项目组成员进行分类
		Map<String, List<MpmProjectTeamEntity>> teamEntityForCode = mpmProjectTeamEntities.stream().collect(Collectors.groupingBy(MpmProjectTeamEntity::getUsercode));
		// 根据sourceid对basechangelog数据进行分类
		Map<String, Map<String, Object>> changelogForId = baseChangeLog.stream().collect(Collectors.toMap(item -> ConvertUtil.convertToString(item.get("sourceid")), item -> item, (v1, v2) -> v1));
		for (String usercode : userSet) {
			StringBufferProxy content = new StringBufferProxy();
			List<MpmProjectTeamEntity> teamEntities = teamEntityForCode.get(usercode);
			if (CollectionUtil.isEmpty(teamEntities)) {
				continue;
			}
			// 新增、变更拼接内容
			List<String> addList = new ArrayList<>(), editList = new ArrayList<>();
			for (MpmProjectTeamEntity teamEntity : teamEntities) {
				Map<String, Object> changelogMap = changelogForId.get(ConvertUtil.convertToString(teamEntity.getId()));
				if (ObjectUtil.isEmpty(changelogMap)) {
					continue;
				}
				this.concatAddEditStr(teamEntity, changelogMap, addList, editList);
			}
			content.appendSingle("【{0}级项目：{1}】任命变更已完成，{2}请知悉。", projectLevel, mpmProjectEntity.getProjectname(), this.convertAppointMessageInfo(addList, editList));
			appList.add(MessageUtil.createMessageAppMap(usercode, title, content.toString(), mpmProjectEntity.getId(),
					MpmProjectAppointmentEntity.tableName, 0));
			sysList.add(MessageUtil.createMessageSysMap(usercode, ConvertUtil.convertToString(userRef.get("usercode")), title, content.toString(),
					mpmProjectEntity.getId(), MpmProjectAppointmentEntity.tableName));
		}
	}
	/***
	 * @description: 将删除内容basechangelog修改为del
	 * @return
	 * @author: houyuhang
	 * @date: 2023/02/13
	 * @modify:
	 */
	public void setChangelogOperate(Map<String, Object> logMap) {
		JSONArray jsonArray = JSONArray.parseArray(ConvertUtil.convertToString(logMap.get("content")));
		for (int i = 0; i < jsonArray.size(); i++) {
			JSONObject jsonObject = jsonArray.getJSONObject(i);
			if (MpmProjectTeamEntity.FieldAppointmenttype.equals(jsonObject.getString("code"))) {
				logMap.put("operatetype", MpmSystemConst.BaseLogOperateTypeEnum.Del);
			}
		}
	}
	/***
	 * @description: 项目组成员新增、变更发送消息拼接
	 * @return
	 * @author: houyuhang
	 * @date: 2023/02/13
	 * @modify:
	 */
	public void concatAddEditStr(MpmProjectTeamEntity teamEntity, Map<String, Object> changelogMap, List<String> addList, List<String> editList) {
		StringBuffer stringBuffer = new StringBuffer();
		if (MpmSystemConst.BaseLogOperateTypeEnum.Add.equals(changelogMap.get("operatetype"))) {
			stringBuffer.append(teamEntity.getWorkgroup()).append(MpmSystemConst.WorkGroupRoleCode.groupLeader.equals(teamEntity.getProjectrole()) ? MpmSystemConst.TeamProjectRole.leader : MpmSystemConst.TeamProjectRole.worker);
			addList.add(stringBuffer.toString());
		} else if (MpmSystemConst.BaseLogOperateTypeEnum.Edit.equals(changelogMap.get("operatetype"))) {
			stringBuffer.append(teamEntity.getWorkgroup()).append(this.getAppointInfoDetail(changelogMap));
			editList.add(stringBuffer.toString());
		}
	}
	/***
	 * @description: 获取任命项目项目组成员变更修改具体字段
	 * @return
	 * @author: houyuhang
	 * @date: 2023/02/06
	 * @modify:
	 */
	public String getAppointInfoDetail(Map<String, Object> logMap) {
		List<String> listStr = new ArrayList<>();
		JSONArray jsonArray = JSONArray.parseArray(ConvertUtil.convertToString(logMap.get("content")));
		for (int i = 0; i < jsonArray.size(); i++) {
			JSONObject jsonObject = jsonArray.getJSONObject(i);
			listStr.add(jsonObject.getString("name"));
		}
		return listStr.stream().collect(Collectors.joining("、"));
	}
	/***
	 * @description: 拼接任命信息
	 * @return
	 * @author: houyuhang
	 * @date: 2023/02/13
	 * @modify:
	 */
	public String convertAppointMessageInfo(List<String> addList, List<String> editList) {
		StringBuffer stringBuffer = new StringBuffer();
		if (!CollectionUtil.isEmpty(addList)) {
			stringBuffer.append("您被任命为").append(addList.stream().collect(Collectors.joining("，"))).append("；");
		}
		if (!CollectionUtil.isEmpty(editList)) {
			stringBuffer.append(editList.stream().collect(Collectors.joining("，"))).append("有变更；");
		}
		return stringBuffer.toString();
	}
	/***
	 * @description: 撤销时查询该责任人是否有未完成的任务
	 * @return
	 * @author: houyuhang
	 * @date: 2023/04/08
	 * @modify:
	 */
	public void checkUnfinishTask(List<MpmProjectTeamEntity> mpmProjectTeamEntities) {
		List<MpmProjectTeamEntity> tempTeamList = new ArrayList<>();
		StringBufferProxy sql = new StringBufferProxy();
		// 判断其他组中是否存在此成员，如果没有此成员，需要判断是否存在未完成的任务
		for (MpmProjectTeamEntity teamEntity : mpmProjectTeamEntities) {
			sql.clear();
			sql.appendSingle("PROJECTCODE = '{0}' and appointmentid = '{1}' and appointmenttype = '1' and teamid != {2} and usercode = '{3}'", teamEntity.getProjectcode(),
					teamEntity.getAppointmentid(), teamEntity.getTeamid(), teamEntity.getUsercode());
			List<MpmProjectTeamEntity> existTeam = this.queryByWhere(sql.toString());
			if (!CollectionUtil.isEmpty(existTeam)) {
				continue;
			}
			tempTeamList.add(teamEntity);
		}
		if (CollectionUtil.isEmpty(tempTeamList)) {
			return;
		}
		// 其他组中不存在此成员，需要判断是否存在未完成的任务
		sql.clear();
		String usercode = tempTeamList.stream().map(MpmProjectTeamEntity::getUsercode).collect(Collectors.joining("','", "'", "'"));
		String taskState = "'" + MpmSystemConst.TaskStateCode.TaskNotStartCode + "','" + MpmSystemConst.TaskStateCode.TaskIncompleteCode + "'";
		sql.appendSingle(" RESPONSIBLECODE in ({0}) and PROJECTCODE= '{1}' and taskstate in ({2}) ", usercode, mpmProjectTeamEntities.get(0).getProjectcode(), taskState);
		List<MpmProjectTaskEntity> mpmProjectTaskEntities = mpmProjectTaskService.queryByWhere(sql.toString());
		if(mpmProjectTaskEntities.size()>0) {
			String alertname = mpmProjectTaskEntities.stream().map(MpmProjectTaskEntity::getResponsible).distinct().collect(Collectors.joining("，"));
			throw new MessageException(alertname + "已被分配任务，请先将负责的任务替换为其他负责人！");
		}
	}
}
